home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gdb.new / gdb-3.98 / gdb / expprint.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-01  |  9.8 KB  |  330 lines

  1. /* Print in infix form a struct expression.
  2.    Copyright (C) 1986, 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GDB.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdio.h>
  21. #include "defs.h"
  22. #include "symtab.h"
  23. #include "param.h"
  24. #include "expression.h"
  25. #include "value.h"
  26.  
  27.  
  28. /* These codes indicate operator precedences, least tightly binding first.  */
  29. /* Adding 1 to a precedence value is done for binary operators,
  30.    on the operand which is more tightly bound, so that operators
  31.    of equal precedence within that operand will get parentheses.  */
  32. /* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
  33.    they are used as the "surrounding precedence" to force
  34.    various kinds of things to be parenthesized.  */
  35. enum precedence
  36. { PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_OR, PREC_AND,
  37.   PREC_LOGIOR, PREC_LOGAND, PREC_LOGXOR, PREC_EQUAL, PREC_ORDER,
  38.   PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
  39.   PREC_HYPER, PREC_PREFIX, PREC_SUFFIX };
  40.  
  41. /* Table mapping opcodes into strings for printing operators
  42.    and precedences of the operators.  */
  43.  
  44. struct op_print
  45. {
  46.   char *string;
  47.   enum exp_opcode opcode;
  48.   /* Precedence of operator.  These values are used only by comparisons.  */
  49.   enum precedence precedence;
  50.   int right_assoc;
  51. };
  52.  
  53. const static struct op_print op_print_tab[] =
  54.   {
  55.     {",", BINOP_COMMA, PREC_COMMA, 0},
  56.     {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
  57.     {"||", BINOP_OR, PREC_OR, 0},
  58.     {"&&", BINOP_AND, PREC_AND, 0},
  59.     {"|", BINOP_LOGIOR, PREC_LOGIOR, 0},
  60.     {"&", BINOP_LOGAND, PREC_LOGAND, 0},
  61.     {"^", BINOP_LOGXOR, PREC_LOGXOR, 0},
  62.     {"==", BINOP_EQUAL, PREC_EQUAL, 0},
  63.     {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
  64.     {"<=", BINOP_LEQ, PREC_ORDER, 0},
  65.     {">=", BINOP_GEQ, PREC_ORDER, 0},
  66.     {">", BINOP_GTR, PREC_ORDER, 0},
  67.     {"<", BINOP_LESS, PREC_ORDER, 0},
  68.     {">>", BINOP_RSH, PREC_SHIFT, 0},
  69.     {"<<", BINOP_LSH, PREC_SHIFT, 0},
  70.     {"+", BINOP_ADD, PREC_ADD, 0},
  71.     {"-", BINOP_SUB, PREC_ADD, 0},
  72.     {"*", BINOP_MUL, PREC_MUL, 0},
  73.     {"/", BINOP_DIV, PREC_MUL, 0},
  74.     {"%", BINOP_REM, PREC_MUL, 0},
  75.     {"@", BINOP_REPEAT, PREC_REPEAT, 0},
  76.     {"-", UNOP_NEG, PREC_PREFIX, 0},
  77.     {"!", UNOP_ZEROP, PREC_PREFIX, 0},
  78.     {"~", UNOP_LOGNOT, PREC_PREFIX, 0},
  79.     {"*", UNOP_IND, PREC_PREFIX, 0},
  80.     {"&", UNOP_ADDR, PREC_PREFIX, 0},
  81.     {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
  82.     {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
  83.     {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
  84.     /* C++  */
  85.     {"::", BINOP_SCOPE, PREC_PREFIX, 0},
  86.   };
  87.  
  88. static void print_subexp ();
  89.  
  90. void
  91. print_expression (exp, stream)
  92.      struct expression *exp;
  93.      FILE *stream;
  94. {
  95.   int pc = 0;
  96.   print_subexp (exp, &pc, stream, PREC_NULL);
  97. }
  98.  
  99. /* Print the subexpression of EXP that starts in position POS, on STREAM.
  100.    PREC is the precedence of the surrounding operator;
  101.    if the precedence of the main operator of this subexpression is less,
  102.    parentheses are needed here.  */
  103.  
  104. static void
  105. print_subexp (exp, pos, stream, prec)
  106.      register struct expression *exp;
  107.      register int *pos;
  108.      FILE *stream;
  109.      enum precedence prec;
  110. {
  111.   register unsigned tem;
  112.   register int pc;
  113.   unsigned nargs;
  114.   register char *op_str;
  115.   int assign_modify = 0;
  116.   enum exp_opcode opcode;
  117.   enum precedence myprec;
  118.   /* Set to 1 for a right-associative operator.  */
  119.   int assoc;
  120.  
  121.   pc = (*pos)++;
  122.   opcode = exp->elts[pc].opcode;
  123.   switch (opcode)
  124.     {
  125.     case OP_SCOPE:
  126.       myprec = PREC_PREFIX;
  127.       assoc = 0;
  128.       (*pos) += 2;
  129.       print_subexp (exp, pos, stream,
  130.             (enum precedence) ((int) myprec + assoc));
  131.       fprintf (stream, " :: ");
  132.       nargs = strlen (&exp->elts[pc + 2].string);
  133.       (*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
  134.  
  135.       fprintf (stream, &exp->elts[pc + 2].string);
  136.       return;
  137.  
  138.     case OP_LONG:
  139.       (*pos) += 3;
  140.       value_print (value_from_long (exp->elts[pc + 1].type,
  141.                     exp->elts[pc + 2].longconst),
  142.            stream, 0, Val_no_prettyprint);
  143.       return;
  144.  
  145.     case OP_DOUBLE:
  146.       (*pos) += 3;
  147.       value_print (value_from_double (exp->elts[pc + 1].type,
  148.                       exp->elts[pc + 2].doubleconst),
  149.            stream, 0, Val_no_prettyprint);
  150.       return;
  151.  
  152.     case OP_VAR_VALUE:
  153.       (*pos) += 2;
  154.       fprintf (stream, "%s", SYMBOL_NAME (exp->elts[pc + 1].symbol));
  155.       return;
  156.  
  157.     case OP_LAST:
  158.       (*pos) += 2;
  159.       fprintf (stream, "$%d", longest_to_int (exp->elts[pc + 1].longconst));
  160.       return;
  161.  
  162.     case OP_REGISTER:
  163.       (*pos) += 2;
  164.       fprintf (stream, "$%s",
  165.            longest_to_int (reg_names[exp->elts[pc + 1].longconst]));
  166.       return;
  167.  
  168.     case OP_INTERNALVAR:
  169.       (*pos) += 2;
  170.       fprintf (stream, "$%s",
  171.            internalvar_name (exp->elts[pc + 1].internalvar));
  172.       return;
  173.  
  174.     case OP_FUNCALL:
  175.       (*pos) += 2;
  176.       nargs = longest_to_int (exp->elts[pc + 1].longconst);
  177.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  178.       fprintf (stream, " (");
  179.       for (tem = 0; tem < nargs; tem++)
  180.     {
  181.       if (tem != 0)
  182.         fprintf (stream, ", ");
  183.       print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
  184.     }
  185.       fprintf (stream, ")");
  186.       return;
  187.  
  188.     case OP_STRING:
  189.       nargs = strlen (&exp->elts[pc + 1].string);
  190.       (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
  191.       fprintf (stream, "\"");
  192.       for (tem = 0; tem < nargs; tem++)
  193.     printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
  194.       fprintf (stream, "\"");
  195.       return;
  196.  
  197.     case TERNOP_COND:
  198.       if ((int) prec > (int) PREC_COMMA)
  199.     fprintf (stream, "(");
  200.       /* Print the subexpressions, forcing parentheses
  201.      around any binary operations within them.
  202.      This is more parentheses than are strictly necessary,
  203.      but it looks clearer.  */
  204.       print_subexp (exp, pos, stream, PREC_HYPER);
  205.       fprintf (stream, " ? ");
  206.       print_subexp (exp, pos, stream, PREC_HYPER);
  207.       fprintf (stream, " : ");
  208.       print_subexp (exp, pos, stream, PREC_HYPER);
  209.       if ((int) prec > (int) PREC_COMMA)
  210.     fprintf (stream, ")");
  211.       return;
  212.  
  213.     case STRUCTOP_STRUCT:
  214.       tem = strlen (&exp->elts[pc + 1].string);
  215.       (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
  216.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  217.       fprintf (stream, ".%s", &exp->elts[pc + 1].string);
  218.       return;
  219.  
  220.     case STRUCTOP_PTR:
  221.       tem = strlen (&exp->elts[pc + 1].string);
  222.       (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
  223.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  224.       fprintf (stream, "->%s", &exp->elts[pc + 1].string);
  225.       return;
  226.  
  227.     case BINOP_SUBSCRIPT:
  228.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  229.       fprintf (stream, "[");
  230.       print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
  231.       fprintf (stream, "]");
  232.       return;
  233.  
  234.     case UNOP_POSTINCREMENT:
  235.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  236.       fprintf (stream, "++");
  237.       return;
  238.  
  239.     case UNOP_POSTDECREMENT:
  240.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  241.       fprintf (stream, "--");
  242.       return;
  243.  
  244.     case UNOP_CAST:
  245.       (*pos) += 2;
  246.       if ((int) prec > (int) PREC_PREFIX)
  247.     fprintf (stream, "(");
  248.       fprintf (stream, "(");
  249.       type_print (exp->elts[pc + 1].type, "", stream, 0);
  250.       fprintf (stream, ") ");
  251.       print_subexp (exp, pos, stream, PREC_PREFIX);
  252.       if ((int) prec > (int) PREC_PREFIX)
  253.     fprintf (stream, ")");
  254.       return;
  255.  
  256.     case UNOP_MEMVAL:
  257.       (*pos) += 2;
  258.       if ((int) prec > (int) PREC_PREFIX)
  259.     fprintf (stream, "(");
  260.       fprintf (stream, "{");
  261.       type_print (exp->elts[pc + 1].type, "", stream, 0);
  262.       fprintf (stream, "} ");
  263.       print_subexp (exp, pos, stream, PREC_PREFIX);
  264.       if ((int) prec > (int) PREC_PREFIX)
  265.     fprintf (stream, ")");
  266.       return;
  267.  
  268.     case BINOP_ASSIGN_MODIFY:
  269.       opcode = exp->elts[pc + 1].opcode;
  270.       (*pos) += 2;
  271.       myprec = PREC_ASSIGN;
  272.       assoc = 1;
  273.       assign_modify = 1;
  274.       for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
  275.     if (op_print_tab[tem].opcode == opcode)
  276.       {
  277.         op_str = op_print_tab[tem].string;
  278.         break;
  279.       }
  280.       break;
  281.  
  282.     case OP_THIS:
  283.       ++(*pos);
  284.       fprintf (stream, "this");
  285.       return;
  286.  
  287.     default:
  288.       for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
  289.     if (op_print_tab[tem].opcode == opcode)
  290.       {
  291.         op_str = op_print_tab[tem].string;
  292.         myprec = op_print_tab[tem].precedence;
  293.         assoc = op_print_tab[tem].right_assoc;
  294.         break;
  295.       }
  296.     }
  297.  
  298.   if ((int) myprec < (int) prec)
  299.     fprintf (stream, "(");
  300.   if ((int) opcode > (int) BINOP_END)
  301.     {
  302.       /* Unary prefix operator.  */
  303.       fprintf (stream, "%s", op_str);
  304.       print_subexp (exp, pos, stream, PREC_PREFIX);
  305.     }
  306.   else
  307.     {
  308.       /* Binary operator.  */
  309.       /* Print left operand.
  310.      If operator is right-associative,
  311.      increment precedence for this operand.  */
  312.       print_subexp (exp, pos, stream,
  313.             (enum precedence) ((int) myprec + assoc));
  314.       /* Print the operator itself.  */
  315.       if (assign_modify)
  316.     fprintf (stream, " %s= ", op_str);
  317.       else if (op_str[0] == ',')
  318.     fprintf (stream, "%s ", op_str);
  319.       else
  320.     fprintf (stream, " %s ", op_str);
  321.       /* Print right operand.
  322.      If operator is left-associative,
  323.      increment precedence for this operand.  */
  324.       print_subexp (exp, pos, stream,
  325.             (enum precedence) ((int) myprec + !assoc));
  326.     }
  327.   if ((int) myprec < (int) prec)
  328.     fprintf (stream, ")");
  329. }
  330.